﻿////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// <copyright>Copyright 2008-2011 Andreas Huber Doenni</copyright>
// Distributed under the GNU General Public License version 2 (GPLv2).
// See accompanying file License.txt or copy at http://phuse.codeplex.com/license.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

namespace Phuse.Net.Forums
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics.CodeAnalysis;
    using System.IO;
    using System.Threading;

    using Phuse.Mime;

    /// <summary>References the method to be called when the header of a new article needs to be saved.</summary>
    public delegate IInboundArticleInfo SaveHeaderCallback(
        long number, string messageId, DateTime? date, string from, string subject, IList<string> references);

    /// <summary>References the method to be called when the content of an article needs to be saved.</summary>
    public delegate void SaveContentCallback(IInboundArticleInfo article, Stream content);

    /// <summary>References the method to be called when an article needs to be deleted.</summary>
    public delegate void DeleteArticleCallback(IInboundArticleInfo article);

    /// <summary>Provides the methods to access a forum through a given host connection.</summary>
    /// <typeparam name="TConnection">The type that represents a connection with the host.</typeparam>
    /// <threadsafety static="true" instance="false"/>
    public interface IForumProvider<TConnection> where TConnection : Connection
    {
        /// <summary>Establishes and returns a connection to <paramref name="host"/>.</summary>
        /// <exception cref="IOException">A connection to the host could not be established.</exception>
        TConnection Connect(IHostInfo host, CancellationToken cancellationToken);

        /// <summary>Sends <paramref name="message"/> using <paramref name="connection"/>.</summary>
        /// <returns>An appropriate exception if the sending of the article failed in an expected manner; otherwise
        /// <c>null</c>.</returns>
        /// <remarks>An expected failure should be signalled by returning the exception rather than throwing it, such
        /// that the caller can continue sending other articles after an expected failure. Unexpected failures must be
        /// signalled by throwing an appropriate exception.</remarks>
        Exception SendArticle(TConnection connection, Message message);

        /// <summary>Gets the current high water mark using <paramref name="connection"/>.</summary>
        /// <exception cref="IOException">The connection to the host has been lost.</exception>
        [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "WaterMark", Justification = "This is not a watermark.")]
        long GetHighWaterMark(TConnection connection, string groupName);

        /// <summary>Receives the article headers using <paramref name="connection"/>.</summary>
        /// <exception cref="IOException">The connection to the host has been lost.</exception>
        void ReceiveHeaders(
            TConnection connection,
            string groupName,
            IInboundArticleInfo lastOldArticle,
            long lastOldArticleNumber,
            SaveHeaderCallback saveHeader,
            SaveContentCallback saveContent);

        /// <summary>Receives the article contents using <paramref name="connection"/>.</summary>
        /// <exception cref="IOException">The connection to the host has been lost.</exception>
        void ReceiveContents(
            TConnection connection,
            string groupName,
            IList<IInboundArticleInfo> contentsToReceive,
            SaveContentCallback saveContent,
            DeleteArticleCallback deleteArticle);
    }
}
